import VmBase from "../../cur/VM/VmBase";


const { ccclass, property, executeInEditMode, menu, help } = cc._decorator;

enum ACTION_MODE {
    查找组件,
    激活组件,
    替换组件,
    删除组件
}

/**查找列表 */
enum FIND_LIST {
    VmBase,
    VmParent,
    VmLabel,
    VmProgress,
    VmState,
}

/**
 * 用于搜索的MV 组件列表，挂载在父节点后，
 * 会遍历搜索下面的所有MV组件, 并且显示其观察值的路径
 */
@ccclass
@executeInEditMode
export default class MVCompsEdit extends cc.Component {

    @property({ displayName: `快速功能` })
    fastEdit = false;

    @property({ displayName: `查找列表`, type: [cc.Enum(FIND_LIST)], visible() { return this.fastEdit; } })
    findList: FIND_LIST[] = [];

    @property({ displayName: `操作类型`, type: cc.Enum(ACTION_MODE), visible() { return this.fastEdit; } })
    actionType: ACTION_MODE = ACTION_MODE.查找组件;

    @property({ displayName: `查找`, tooltip: '勾选后,会自动查找 find list 中填写的组件', visible() { return this.actionType === ACTION_MODE.查找组件 && this.fastEdit; } })
    get findTrigger() { return false; }
    set findTrigger(v: boolean) { this.setComponents(0); }

    @property({ displayName: `激活`, tooltip: '勾选后,会批量激活 find list 中填写的组件', visible() { return this.actionType === ACTION_MODE.激活组件 && this.fastEdit; } })
    get enableTrigger() { return false; }
    set enableTrigger(v: boolean) { this.setComponents(1); }

    @property({ displayName: `关闭`, tooltip: '勾选后,会批量关闭 find list 中填写的组件', visible() { return this.actionType === ACTION_MODE.激活组件 && this.fastEdit; } })
    get disableTrigger() { return false; }
    set disableTrigger(v: boolean) { this.setComponents(2); }

    @property({ displayName: `允许删除`, tooltip: '允许删除节点的组件,确定需要移除请勾选,防止误操作', visible() { return this.actionType === ACTION_MODE.删除组件 && this.fastEdit; } })
    allowDelete: boolean = false;

    @property({ displayName: '[ X DELETE X ]', tooltip: '勾选后,会批量删除 find list 中填写的组件', visible() { return this.allowDelete && this.actionType === ACTION_MODE.删除组件 && this.fastEdit; } })
    get deleteTrigger() { return false; }
    set deleteTrigger(v: boolean) { this.setComponents(3); }

    @property({ displayName: `开头路径`, tooltip: '匹配的路径,匹配规则: 搜索开头为 game的路径', visible() { return this.actionType === ACTION_MODE.替换组件 && this.fastEdit; } })
    targetPath: string = 'game';

    @property({ displayName: `替换路径`, tooltip: '替换的路径,将匹配到的路径替换', visible() { return this.actionType === ACTION_MODE.替换组件 && this.fastEdit; } })
    replacePath: string = '*';

    @property({ displayName: `替换`, tooltip: '勾选后,会批量替换掉指定的路径', visible() { return this.actionType === ACTION_MODE.替换组件 && this.fastEdit; } })
    get replaceTrigger() { return false; }
    set replaceTrigger(v: boolean) { this.setComponents(4); }

    @property({ displayName: `显示引用`, tooltip: '是否搜集绑定VM组件的节点?', visible() { return this.actionType === ACTION_MODE.查找组件 && this.fastEdit; } })
    canCollectNodes: boolean = false;

    @property({ displayName: `查找到的引用`, type: [cc.Node], readonly: true, tooltip: '收集到绑定了VM组件相关的节点，可以自己跳转过去', visible() { return this.canCollectNodes && this.actionType === ACTION_MODE.查找组件 && this.fastEdit; } })
    collectNodes: cc.Node[] = [];

    /**设置组件 */
    setComponents(state: number) {
        let title = '搜索到当前节点下面的组件';
        switch (state) {
            case 0: title = '搜索到当前节点下面的组件'; break;
            case 1: title = '激活以下节点的组件'; break;
            case 2: title = '关闭以下节点的组件'; break;
            case 3: title = '删除以下节点的组件'; break;
            case 4: title = '替换以下节点的路径'; break;
            default: break;
        }
        cc.log(title)
        cc.log('______________________')
        this.findList.forEach(findEnum => this.searchComponent(FIND_LIST[findEnum], state));
        cc.log('______________________')
    }

    /**
     * 查找组件并设置
     * @param className 
     * @param state 0-查找节点组件 1-激活节点组件 2-关闭节点组件 3-移除节点组件
     */
    searchComponent(className: string, state: number = 0) {
        /**收集节点清空 */
        this.collectNodes = [];

        let comps = this.node.getComponentsInChildren(className) as VmBase[];
        if (comps == null || comps.length < 1) return;
        cc.log('[' + className + ']:');
        comps.forEach(v => {
            let ext = '';
            if (state <= 3) {
                //区分模板模式路径
                if (v.useMultipathMode && v.watchPathArr) {
                    ext = `  Path:[${v.watchPathArr.join(' | ')}]`;
                } else if (v.watchPath) {
                    ext = `  Path:[${v.watchPath}]`;
                }
            }
            cc.log(this.getNodePath(v.node) + ext);

            switch (state) {
                case 0:
                    if (this.canCollectNodes && this.collectNodes.indexOf(v.node) === -1) {
                        this.collectNodes.push(v.node);
                    }
                    break;
                case 1: v.enabled = true; break;
                case 2: v.enabled = false; break;
                case 3: v.node.removeComponent(v); break;
                case 4://替换指定路径
                    let targetPath = this.targetPath;
                    let replacePath = this.replacePath;
                    if (v.useMultipathMode) {
                        v.watchPathArr.forEach((path, i) => {
                            v.watchPathArr[i] = this._replaceNodePath(path, targetPath, replacePath);
                        });
                    } else {
                        v.watchPath = this._replaceNodePath(v.watchPath, targetPath, replacePath);
                    }
                default: break;
            }
        });
    }

    /**替换路径 */
    _replaceNodePath(path: string, search: string, replace: string) {
        let pathArr = path.split('.');
        let searchArr = search.split('.');
        let replaceArr = replace.split('.')
        let match = true;
        for (let i = 0; i < searchArr.length; i++) {
            if (pathArr[i] !== searchArr[i]) {
                //未匹配上
                match = false;
                break;
            }
        }
        //匹配成功准备替换路径
        if (match) {
            for (let i = 0; i < replaceArr.length; i++) {
                pathArr[i] = replaceArr[i];
            }
            cc.log(' 路径更新:', path, '>>>', pathArr.join('.'))
        }
        return pathArr.join('.');
    }

    /**查找节点路径 */
    getNodePath(parentNode: cc.Node) {
        let array = [];
        while (parentNode) {
            let p = parentNode.parent;
            if (p) {
                array.push(parentNode.name);
                parentNode = p;
            } else {
                break;
            }
        }
        return array.reverse().join('/');
    }



    // update (dt) {}
}
